java 同步锁(synchronized)的正确使用姿势

关于线程安全,线程锁我们经常会用到,但你的使用姿势正确不,反正我用错了好长一段时间而不自知。所以有了这篇博客总结下线程锁的正确打开姿势
废话不说看例子
一,对整个方法进行加锁
1,对整个方法进行加锁,不同线程访问同一个类的同一个对象
public class TestRunnable implements Runnable {

	@Override
	public synchronized  void run() {
		// TODO Auto-generated method stub
			for(int i=0;i<10;i++)
			{
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"---"+i);
			}
		}
	

}
public static void main(String[] args)
	{
		TestRunnable runnable=new TestRunnable();
		Thread threadA=new Thread(runnable,"threadA");
		threadA.start();
		
		Thread threadB=new Thread(runnable,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9


2,对整个方法进行加锁,不同线程访问同一个类的不同对象
public class TestRunnable implements Runnable {

	@Override
	public synchronized  void run() {
		// TODO Auto-generated method stub
			for(int i=0;i<10;i++)
			{
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"---"+i);
			}
		}
	

}
	public static void main(String[] args)
	{
		TestRunnable runnableA=new TestRunnable();
		Thread threadA=new Thread(runnableA,"threadA");
		threadA.start();
		
		TestRunnable runnableB=new TestRunnable();
		Thread threadB=new Thread(runnableB,"threadB");
		threadB.start();
	}
运行结果:
threadB---0
threadA---0
threadA---1
threadB---1
threadA---2
threadB---2
threadA---3
threadB---3
threadB---4
threadA---4
threadA---5
threadB---5
threadA---6
threadB---6
threadA---7
threadB---7
threadA---8
threadB---8
threadA---9
threadB---9

小结:对方法整体加锁的做法适用条件是 多个线程访问的必须是同一个类的同一个实例对象


一,对代码块进行加锁
1,对代码块进行加锁,加锁对象为当前类对象,不同线程访问同一个类的同一个对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (TestRunnable.this) {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}
public static void main(String[] args)
	{
		TestRunnable runnable=new TestRunnable();
		Thread threadA=new Thread(runnable,"threadA");
		threadA.start();
		
		Thread threadB=new Thread(runnable,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9


2,对代码块进行加锁,加锁对象为当前类对象,不同线程访问同一个类的不同对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (TestRunnable.this) {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}

	public static void main(String[] args)
	{
		TestRunnable runnableA=new TestRunnable();
		Thread threadA=new Thread(runnableA,"threadA");
		threadA.start();
		
		TestRunnable runnableB=new TestRunnable();
		Thread threadB=new Thread(runnableB,"threadB");
		threadB.start();
	}


运行结果:
threadB---0
threadA---0
threadB---1
threadA---1
threadB---2
threadA---2
threadA---3
threadB---3
threadA---4
threadB---4
threadB---5
threadA---5
threadA---6
threadB---6
threadB---7
threadA---7
threadA---8
threadB---8
threadA---9
threadB---9


3,对代码块进行加锁,加锁对象为当前类(不是类对象哦),不同线程访问同一个类的同一个对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (TestRunnable.class) {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}
public static void main(String[] args)
	{
		TestRunnable runnable=new TestRunnable();
		Thread threadA=new Thread(runnable,"threadA");
		threadA.start();
		
		Thread threadB=new Thread(runnable,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9


4,对代码块进行加锁,加锁对象为当前类(不是类对象哦),不同线程访问同一个类的不同对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (TestRunnable.class) {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}
	public static void main(String[] args)
	{
		TestRunnable runnableA=new TestRunnable();
		Thread threadA=new Thread(runnableA,"threadA");
		threadA.start();
		
		TestRunnable runnableB=new TestRunnable();
		Thread threadB=new Thread(runnableB,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9


5,对代码块进行加锁,加锁对象为已赋值的变量,不同线程访问同一个类的同一个对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized ("test") {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}
public static void main(String[] args)
	{
		TestRunnable runnable=new TestRunnable();
		Thread threadA=new Thread(runnable,"threadA");
		threadA.start();
		
		Thread threadB=new Thread(runnable,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9


6,对代码块进行加锁,加锁对象为已赋值的变量,不同线程访问同一个类的不同对象
public class TestRunnable implements Runnable {


	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized ("test") {
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "---" + i);
			}
		}
	}


}
	public static void main(String[] args)
	{
		TestRunnable runnableA=new TestRunnable();
		Thread threadA=new Thread(runnableA,"threadA");
		threadA.start();
		
		TestRunnable runnableB=new TestRunnable();
		Thread threadB=new Thread(runnableB,"threadB");
		threadB.start();
	}
运行结果:
threadA---0
threadA---1
threadA---2
threadA---3
threadA---4
threadA---5
threadA---6
threadA---7
threadA---8
threadA---9
threadB---0
threadB---1
threadB---2
threadB---3
threadB---4
threadB---5
threadB---6
threadB---7
threadB---8
threadB---9

小结:当对代码块进行加锁时,当加锁对象是一个确定值时(当前类,或者已赋值的变量) 不同线程访问同一个类的不同对象时也可以实现线程同步

最后奉上线程锁在实际开发中的应用----单例模式

1,懒汉式写法
public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    public static synchronized Singleton getInstance() {
	if (instance == null) {
	    instance = new Singleton();
	}
	return instance;
    }
}
2,懒汉式写法升级版(双重校验锁) 性能优于第一种
public class Singleton {  
    private static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
} 

3,饿汉式写法,不依赖于线程同步锁,依赖于静态变量和类的同步加载实现线程安全
public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton (){}
    public static Singleton getInstance() {
	return instance;
    }
}











  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Java中的synchronized关键字是一种用于实现同步的机制。它可以应用于方法和代码块,以确保在同一时刻只有一个线程可以访问共享资源。 以下是一些使用synchronized关键字的案例: 1. 多线程访问共享资源:考虑一个银行账户的例子,多个线程同时尝试改变账户余额。为了避免竞态条件和数据不一致的问题,可以使用synchronized关键字来同步访问共享资源,例如在deposit()和withdraw()方法上使用synchronized。 2. 线程安全的容器:在多线程环境下,使用synchronized可以确保线程安全的访问容器。例如,可以在对ArrayList的增删操作上使用synchronized,以避免多个线程同时修改容器而导致的错误。 3. 生产者-消费者模型:生产者线程负责生成数据,消费者线程负责消费数据。为了保证顺序,可以使用synchronized来同步这两个线程。例如,在生产者方法的代码块和消费者方法的代码块上使用synchronized。 4. 对象锁和类锁:synchronized可以用来实现对象级别的锁和类级别的锁。对象级别的锁是在每个对象实例上加锁,而类级别的锁是在类级别上加锁。例如,在静态方法上使用synchronized即可获得类级别的锁。 总结来说,synchronized关键字在Java中的使用案例非常广泛,可以用于多线程环境下保证共享资源的安全访问,避免并发操作导致的数据不一致问题。通过使用synchronized,可以有效地控制多个线程对共享资源的访问,确保线程安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值